package com.duobaoyu.dby.supply.biz.service.refund.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.duobaoyu.dby.channel.adapter.enums.biz.invoice.InvoiceStatusEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.refund.AfterSaleStatusEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.refund.AfterSaleTypeEnum;
import com.duobaoyu.dby.channel.adapter.util.ChannelCodeUtils;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.mybatis.config.IdGeneratorSnowflake;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.OrderBO;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.OrderProductBO;
import com.duobaoyu.dby.supply.biz.converter.AfterSaleServiceConverter;
import com.duobaoyu.dby.supply.biz.enums.AfterSaleSourceEnum;
import com.duobaoyu.dby.supply.biz.exception.SupplyChainBizException;
import com.duobaoyu.dby.supply.biz.service.refund.AfterSaleService;
import com.duobaoyu.dby.supply.biz.service.refund.event.AfterSaleCreateEvent;
import com.duobaoyu.dby.supply.common.biz.bo.refund.*;
import com.duobaoyu.dby.supply.common.biz.dto.refund.AfterSaleApplyQueryDTO;
import com.duobaoyu.dby.supply.common.biz.dto.refund.AfterSaleBatchQuery;
import com.duobaoyu.dby.supply.common.biz.vo.refund.AfterSaleExportVO;
import com.duobaoyu.dby.supply.common.biz.vo.refund.AfterSaleListVO;
import com.duobaoyu.dby.supply.core.common.exception.CustomAssert;
import com.duobaoyu.dby.supply.db.entity.refund.*;
import com.duobaoyu.dby.supply.db.repository.refund.*;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum.*;

/**
 * @author yw
 * @description
 * @date 2023/9/27 15:33
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AfterSaleServiceImpl implements AfterSaleService {

    private final AfterSaleRepository afterSaleRepository;
    private final AfterSaleItemRepository afterSaleItemRepository;
    private final AfterSalesPickupRepository afterSalesPickupRepository;
    private final AfterSalesReturnRepository afterSalesReturnRepository;
    private final AfterSalesLogisticsRepository afterSalesLogisticsRepository;
    private final AfterSaleServiceConverter afterSaleServiceConverter;
    private final IdGeneratorSnowflake idGeneratorSnowflake;
    private final AfterSaleImageRepository afterSaleImageRepository;


    @Override
    public List<AfterSaleOutBO> batchQueryAfterSale(AfterSaleBatchQuery batchQuery) {
        List<AfterSale> afterSales = afterSaleRepository.list(Wrappers.<AfterSale>lambdaQuery()
                .in(CollectionUtils.isNotEmpty(batchQuery.getChannelAfterSaleSns()), AfterSale::getChannelAfterSaleSn, batchQuery.getChannelAfterSaleSns())
                .in(CollectionUtils.isNotEmpty(batchQuery.getStatusList()), AfterSale::getStatus, batchQuery.getStatusList())
                .in(CollectionUtils.isNotEmpty(batchQuery.getChannelOrderSns()), AfterSale::getChannelOrderSn, batchQuery.getChannelOrderSns())
				.orderByAsc(AfterSale::getId)
				.last("limit " + CommonConstants.HUNDRED));
        List<AfterSaleOutBO> afterSaleOutList = afterSaleServiceConverter.assembleAfterSale(afterSales);
        if (CollectionUtils.isNotEmpty(afterSaleOutList)) {
            List<String> afterSaleSns = afterSaleOutList.stream().map(AfterSaleOutBO::getAfterSaleSn).collect(Collectors.toList());
            List<AfterSaleItem> afterSaleItemList = afterSaleItemRepository.list(Wrappers.<AfterSaleItem>lambdaQuery()
                    .in(AfterSaleItem::getAfterSaleSn, afterSaleSns));
            Map<String, List<AfterSaleItem>> afterSaleItemGroup = afterSaleItemList.stream()
                    .collect(Collectors.groupingBy(AfterSaleItem::getAfterSaleSn));
            afterSaleOutList.forEach(e -> e.setItems(afterSaleServiceConverter.assembleAfterSaleItems(afterSaleItemGroup.get(e.getAfterSaleSn()))));
        }
        return afterSaleOutList;
    }

    @Override
    public boolean saveAfterSaleImage(AfterSaleImage afterSaleImage) {
        return afterSaleImageRepository.save(afterSaleImage);
    }

    @Override
    public int selectImageCount(Set<String> questionPicList) {
        List<AfterSaleImage> afterSaleImages = afterSaleImageRepository.lambdaQuery()
                .in(AfterSaleImage::getImageHash, questionPicList)
                .list();
        return afterSaleImages.size();
    }

    @Override
    public Page<AfterSaleExportVO> getAfterSaleExportPage(Page<Object> page, AfterSaleApplyQueryDTO afterSaleApplyQuery) {
        return afterSaleRepository.queryExportPage(page, afterSaleApplyQuery);
    }

    /**
     * 售后订单导出总数
     *
     * @param afterSaleApplyQuery
     * @return
     */
    @Override
    public long getAfterSaleExportCount(AfterSaleApplyQueryDTO afterSaleApplyQuery) {
        return afterSaleRepository.afterSaleExportCount(afterSaleApplyQuery);
    }

    @Override
    public AfterSaleOutBO queryAppliedAutoCancelAfterSale(String orderSn) {
        AfterSale afterSale = afterSaleRepository.getOne(Wrappers.<AfterSale>lambdaQuery()
                .eq(AfterSale::getOrderSn, orderSn)
                .notIn(AfterSale::getStatus,AfterSaleStatusEnum.FAIL.getValue())
                .eq(AfterSale::getAfterSaleSource, AfterSaleSourceEnum.SYSTEM.getValue()));
        AfterSaleOutBO afterSaleOut = afterSaleServiceConverter.assembleAfterSale(afterSale);
        if (Objects.nonNull(afterSaleOut)) {
            List<AfterSaleItem> afterSaleItemList =
                    afterSaleItemRepository.list(Wrappers.<AfterSaleItem>lambdaQuery()
                            .eq(AfterSaleItem::getAfterSaleSn, afterSale.getAfterSaleSn()));
            List<AfterSaleItemOutBO> afterSaleItemOutList = afterSaleServiceConverter.assembleAfterSaleItems(afterSaleItemList);
            afterSaleOut.setItems(afterSaleItemOutList);

        }
        return afterSaleOut;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeSystemCreateAfterSaleFail(String orderSn) {
        CustomAssert.hasLength(orderSn, "订单编号不可为空");
        if(log.isDebugEnabled()) {
            log.debug("订单 orderSn:{}, 已发货，该订单售后单变更为失败", orderSn);
        }
        List<AfterSale> afterSaleList = afterSaleRepository.list(Wrappers.<AfterSale>lambdaQuery()
                .eq(StringUtils.isNotBlank(orderSn), AfterSale::getOrderSn, orderSn)
                .eq(AfterSale::getAfterSaleSource, AfterSaleSourceEnum.SYSTEM.getValue())
                .notIn(AfterSale::getChannelCode, Lists.newArrayList(
                        ALIBABA_DISTRIBUTION.getValue(), DE_LI.getValue(), LINKED_MALL.getValue(), ZKH.getValue()))
                .notIn(AfterSale::getStatus, AfterSaleStatusEnum.FAIL.getValue()));
        if (CollectionUtils.isEmpty(afterSaleList)) {
            return Boolean.TRUE;
        }

        List<String> afterSaleSns = afterSaleList.stream()
				.map(AfterSale::getAfterSaleSn)
				.collect(Collectors.toList());
		afterSaleRepository.update(Wrappers.<AfterSale>lambdaUpdate()
				.set(AfterSale::getStatus, AfterSaleStatusEnum.FAIL.getValue())
				.in(AfterSale::getAfterSaleSn, afterSaleSns));
		afterSaleItemRepository.update(Wrappers.<AfterSaleItem>lambdaUpdate()
				.set(AfterSaleItem::getAfterSaleStatus, AfterSaleStatusEnum.FAIL.getValue())
				.in(AfterSaleItem::getAfterSaleSn, afterSaleSns));
        return Boolean.TRUE;
    }

    @Override
    public Boolean modifyAfterSale(AfterSaleModifyInBO modify) {
        AfterSale afterSale = afterSaleServiceConverter.convertAfterSale(modify);
        List<AfterSaleItem> afterSaleItems = afterSaleServiceConverter.convertAfterSalesItem(modify.getAfterSaleItems());
        afterSaleRepository.updateById(afterSale);
        if(CollectionUtils.isNotEmpty(afterSaleItems)){
            afterSaleItems.forEach(afterSaleItemRepository::updateById);
        }
        return true;
    }

	@Override
	public Long waitReview() {
		return afterSaleRepository.getBaseMapper().selectCount(Wrappers.<AfterSale>lambdaQuery().eq(AfterSale::getStatus,AfterSaleStatusEnum.WAIT_DBY_AUDIT.getValue()));
	}

	@Override
	public Boolean modifyCustomerReturnInfo(AfterSaleCustomerReturnInfoInBO customerReturnInfoInBO) {
		AfterSale afterSale = AfterSale.builder()
				.id(customerReturnInfoInBO.getId())
				.customerReturnAddress(afterSaleServiceConverter.convertReturnAddress(customerReturnInfoInBO.getCustomerReturnAddress()))
				.build();
		return afterSaleRepository.updateById(afterSale);
	}

	@Override
    public AfterSaleOutBO queryAfterSale(AfterSaleQuery afterSaleQuery) {
        AfterSale afterSale = afterSaleRepository.getOne(Wrappers.<AfterSale>lambdaQuery()
                .eq(StringUtils.isNotBlank(afterSaleQuery.getAfterSaleSn()), AfterSale::getAfterSaleSn, afterSaleQuery.getAfterSaleSn())
                .eq(StringUtils.isNotBlank(afterSaleQuery.getBizAfterSaleSn()), AfterSale::getBizAfterSaleSn, afterSaleQuery.getBizAfterSaleSn())
                .eq(StringUtils.isNotBlank(afterSaleQuery.getAfterSaleTradeOrderSn()), AfterSale::getAfterSaleTradeOrderSn, afterSaleQuery.getAfterSaleTradeOrderSn()));
        CustomAssert.notNull(afterSale, "售后单不存在");

        AfterSaleOutBO afterSaleOut = afterSaleServiceConverter.assembleAfterSale(afterSale);
        List<AfterSaleItem> afterSaleItemList =
                afterSaleItemRepository.list(Wrappers.<AfterSaleItem>lambdaQuery()
                        .eq(AfterSaleItem::getAfterSaleSn, afterSale.getAfterSaleSn()));
        List<AfterSaleItemOutBO> afterSaleItemOutList = afterSaleServiceConverter.assembleAfterSaleItems(afterSaleItemList);
        afterSaleOut.setItems(afterSaleItemOutList);
        return afterSaleOut;
    }

    /**
     * 拆分
     *
     * @param split
     * @return
     */
    @Override
    public List<AfterSaleCreateInBO> afterSaleSplit(AfterSaleCreateSplitInBO split, List<OrderBO> orders) {
        if (EnumUtils.eq(AfterSaleSourceEnum.SYSTEM, split.getAfterSaleSource())) {
            List<AfterSaleCreateInBO> ret = Lists.newArrayList();
            Map<String, List<AfterSaleCreateSplitInBO.Item>> orderGroup = split.getItems().stream()
                    .collect(Collectors.groupingBy(AfterSaleCreateSplitInBO.Item::getOrderSn));
            orderGroup.forEach((k, v) -> {
                List<AfterSaleItemInBO> items = v.stream().map(e -> convertAfterSaleItem(split, e, orders))
                        .collect(Collectors.toList());
                populateChannelFreightApplyRefundAmount(items, orders);
                AfterSaleCreateInBO afterSale = convertAfterSaleCreate(split, items, orders);
                ret.add(afterSale);
            });
            return ret;
        } else {
            List<AfterSaleCreateSplitInBO.Item> items = split.getItems();
            Map<String, BigDecimal> orderChannelToApplyFreightMap = calculateOrderToApplyFreightRefund(orders, items);
            return items.stream().map(e -> {
                AfterSaleItemInBO item = convertAfterSaleItem(split, e, orders);
                if (EnumUtils.eq(AfterSaleTypeEnum.REFUND, split.getAfterSaleType())
                        || EnumUtils.eq(AfterSaleTypeEnum.RETURNED, split.getAfterSaleType())) {
                    item.setFreightApplyRefundAmount(orderChannelToApplyFreightMap.get(e.getOrderSn()));
                    orderChannelToApplyFreightMap.put(e.getOrderSn(), orderChannelToApplyFreightMap.get(e.getOrderSn())
                            .subtract(item.getFreightApplyRefundAmount()));
                } else {
                    item.setApplyRefundAmount(BigDecimal.ZERO);
                    item.setFreightApplyRefundAmount(BigDecimal.ZERO);
                }
                return convertAfterSaleCreate(split, Lists.newArrayList(item), orders);
            }).collect(Collectors.toList());
        }
    }

    @NotNull
    private Map<String, BigDecimal> calculateOrderToApplyFreightRefund(List<OrderBO> orders, List<AfterSaleCreateSplitInBO.Item> items) {
        Map<String, BigDecimal> orderChannelFreightMap = orders.stream()
                .collect(Collectors.toMap(OrderBO::getOrderSn, OrderBO::getChannelFreightAmount));
        List<String> orderSns = items.stream().map(AfterSaleCreateSplitInBO.Item::getOrderSn)
                .collect(Collectors.toList());
        List<AfterSale> afterSales = afterSaleRepository.list(Wrappers.<AfterSale>lambdaQuery()
                .in(AfterSale::getOrderSn, orderSns)
                .notIn(AfterSale::getStatus, Lists.newArrayList(AfterSaleStatusEnum.FAIL.getValue(),
                        AfterSaleStatusEnum.CLOSE.getValue())));
        afterSales.forEach(afterSale -> {
            if (orderChannelFreightMap.containsKey(afterSale.getOrderSn())) {
                BigDecimal channelFreightActualRefundAmount = Optional.ofNullable(afterSale.getChannelFreightActualRefundAmount())
                        .orElse(BigDecimal.ZERO);
                orderChannelFreightMap.put(afterSale.getOrderSn(),
                        orderChannelFreightMap.get(afterSale.getOrderSn())
                                .subtract(channelFreightActualRefundAmount));
            }
        });
        return orderChannelFreightMap;
    }


    private AfterSaleCreateInBO convertAfterSaleCreate(AfterSaleCreateSplitInBO split, List<AfterSaleItemInBO> items,
                                                       List<OrderBO> orders) {
        Map<String, OrderBO> orderMap = orders.stream().collect(Collectors.toMap(OrderBO::getOrderSn, Function.identity()));
        String orderSn = CollUtil.getFirst(items).getOrderSn();
        AfterSaleCreateInBO afterSale = new AfterSaleCreateInBO();
        afterSale.setAfterSaleSource(split.getAfterSaleSource());
        OrderBO order = orderMap.get(orderSn);
        afterSale.setChannelCode(order.getChannelCode());
        afterSale.setChannelOrderSn(order.getChannelOrderSn());
        afterSale.setChannelOrderParentSn(order.getChannelOrderParentSn());
        afterSale.setChannelTradeOrderSn(order.getChannelTradeOrderSn());
        afterSale.setOrderTradeSn(order.getOrderTradeSn());
        afterSale.setAfterSaleItems(items);
        afterSale.setMchId(order.getMchId());
        afterSale.setUserId(order.getUserId());
        afterSale.setHasInvoice(EnumUtils.eq(InvoiceStatusEnum.APPLIED, order.getInvoiceStatus()));
        afterSale.setOrderSn(orderSn);
        afterSale.setShowServerName(split.getShowServerName());
        afterSale.setApplyRefundAmount(afterSale.getAfterSaleItems().stream()
                .map(AfterSaleItemInBO::getApplyRefundAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        afterSale.setFreightApplyRefundAmount(afterSale.getAfterSaleItems().stream()
                .map(AfterSaleItemInBO::getFreightApplyRefundAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        afterSale.setAfterSaleSource(split.getAfterSaleSource());
        afterSale.setServerName(split.getServerName());
        afterSale.setAfterSaleType(split.getAfterSaleType());
        afterSale.setBizAfterSaleSn(split.getBizAfterSaleSn());
        afterSale.setPickUp(Optional.ofNullable(split.getPickUpMap()).map(e -> e.get(orderSn)).orElse(null));
        afterSale.setReturnShipment(Optional.ofNullable(split.getReturnShipmentMap()).map(e -> e.get(orderSn)).orElse(null));
        afterSale.setContactInfo(Optional.ofNullable(split.getCustomerInfoMap()).map(e -> e.get(orderSn)).orElse(null));
        return afterSale;
    }


    private static AfterSaleItemInBO convertAfterSaleItem(AfterSaleCreateSplitInBO split,
                                                          AfterSaleCreateSplitInBO.Item e,
                                                          List<OrderBO> orders) {
        Map<String, OrderProductBO> itemMap = orders.stream()
                .flatMap(o -> o.getOrderProductList().stream())
                .collect(Collectors.toMap(OrderProductBO::getSkuCode, Function.identity()));
        AfterSaleItemInBO item = new AfterSaleItemInBO();
        item.setOrderSn(e.getOrderSn());
        item.setShowServerName(split.getShowServerName());
        item.setGoodsStatus(e.getGoodStatus());
        item.setReasonCode(e.getReasonCode());
        item.setAfterSaleSource(split.getAfterSaleSource());
        item.setAfterSaleType(split.getAfterSaleType());
        item.setReasonName(e.getReasonName());
        item.setApplyNum(e.getApplyNum());
        item.setAfterSaleRemark(e.getQuestionDesc());
        item.setAfterSaleImageList(e.getQuestionPic());
        item.setBizAfterSaleSn(split.getBizAfterSaleSn());
        item.setSkuCode(e.getSkuCode());
        item.setApplyRefundAmount(e.getApplyRefundAmount());
        item.setFreightApplyRefundAmount(BigDecimal.ZERO);
        item.setServerName(split.getServerName());
        item.setChannelCode(itemMap.get(item.getSkuCode()).getChannelCode());
        item.setProductType(itemMap.get(item.getSkuCode()).getProductType());
        item.setChannelProductCode(itemMap.get(item.getSkuCode()).getChannelProductCode());
        item.setChannelSkuCode(itemMap.get(item.getSkuCode()).getChannelSkuCode());
        item.setProductCode(itemMap.get(item.getSkuCode()).getProductCode());
        item.setSkuCode(itemMap.get(item.getSkuCode()).getSkuCode());
        item.setSkuName(itemMap.get(item.getSkuCode()).getSkuName());
        item.setSkuPic(itemMap.get(item.getSkuCode()).getSkuPic());
        item.setThirdClassifyId(itemMap.get(item.getSkuCode()).getThirdClassifyId());
        item.setPurchaseNum(itemMap.get(item.getSkuCode()).getSkuNum());
        item.setThirdClassifyName(itemMap.get(item.getSkuCode()).getThirdClassifyName());
        item.setChannelActualPaidAmount(itemMap.get(item.getSkuCode()).getChannelPayAmount());
        item.setMerchantActualPaidAmount(itemMap.get(item.getSkuCode()).getPlatformSellAmount());
        item.setItemPlatformUnitPrice(itemMap.get(item.getSkuCode()).getPlatformPrice());
        return item;
    }

    private void populateChannelFreightApplyRefundAmount(List<AfterSaleItemInBO> items, List<OrderBO> orders) {
        Map<String, BigDecimal> orderChannelToApplyFreightMap = orders.stream()
                .collect(Collectors.toMap(OrderBO::getOrderSn, OrderBO::getChannelFreightAmount));
        AfterSaleItemInBO first = CollUtil.getFirst(items);
        first.setFreightApplyRefundAmount(orderChannelToApplyFreightMap.get(first.getOrderSn()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AfterSaleApplyOutBO afterSaleApply(List<AfterSaleCreateInBO> afterSales) {
        afterSales.forEach(e -> {

            boolean exists = afterSaleRepository.exists(Wrappers.lambdaQuery(AfterSale.class)
                    .eq(AfterSale::getBizAfterSaleSn, e.getBizAfterSaleSn())
                    .eq(AfterSale::getOrderSn, e.getOrderSn())
                    .eq(AfterSale::getServerName, e.getServerName())
            );
            if (exists) {
                SupplyChainBizException.fail("业务售后单号[" + e.getBizAfterSaleSn() + "]已存在！");
            }
        });

        List<AfterSaleItem> afterSaleItems = Lists.newArrayList();
        afterSales.forEach(e -> {
            e.setAfterSaleSn(String.valueOf(idGeneratorSnowflake.snowflakeId()));
            e.setAfterSaleTradeOrderSn(e.getAfterSaleSn());
            if (EnumUtils.eq(AfterSaleSourceEnum.SYSTEM, e.getAfterSaleSource())) {
                e.setStatus(ChannelCodeUtils.isSupportOrderCancelByAfterSale(e.getChannelCode()) ?
                        AfterSaleStatusEnum.TO_BE_SUBMITTED_FOR_CHANNEL.getValue() :
                        AfterSaleStatusEnum.WAIT_DBY_AUDIT.getValue());
            } else {
                e.setStatus(AfterSaleStatusEnum.WAIT_DBY_AUDIT.getValue());
            }
            AfterSale afterSale = afterSaleServiceConverter.convertAfterSale(e);
            afterSaleRepository.save(afterSale);
            e.getAfterSaleItems().forEach(item -> {
                AfterSaleItem applyItem = afterSaleServiceConverter.convertAfterSalesItem(item);
                applyItem.setAfterSaleStatus(e.getStatus());
                applyItem.setAfterSaleSn(afterSale.getAfterSaleSn());
                afterSaleItemRepository.save(applyItem);
                afterSaleItems.add(applyItem);
                AfterSalePickUp afterSalePickup = afterSaleServiceConverter.convertAfterSalesPickup(e.getPickUp());
                if (Objects.nonNull(afterSalePickup)) {
                    afterSalePickup.setAfterSaleSn(afterSale.getAfterSaleSn());
                    afterSalesPickupRepository.save(afterSalePickup);
                }
                AfterSaleReturn afterSaleReturn = afterSaleServiceConverter.convertAfterSalesReturn(e.getReturnShipment());
                if (Objects.nonNull(afterSaleReturn)) {
                    afterSaleReturn.setAfterSaleSn(afterSale.getAfterSaleSn());
                    afterSalesReturnRepository.save(afterSaleReturn);
                }
            });
            AfterSaleCreateEvent event = new AfterSaleCreateEvent();
            event.setChannelAfterSaleTradeOrderSn(e.getAfterSaleTradeOrderSn());
            event.setAfterSaleSn(e.getAfterSaleSn());
            event.setAfterSaleType(e.getAfterSaleType());
            event.setOrderSn(e.getOrderSn());
            event.setAfterSaleStatus(e.getStatus());
            event.setOrderAutoCancel(EnumUtils.eq(AfterSaleSourceEnum.SYSTEM, afterSale.getAfterSaleSource()));
            event.setAuditRule(e.getAuditRule());
            event.setSkuList(e.getAfterSaleItems().stream().map(item -> {
                AfterSaleCreateEvent.Sku sku = new AfterSaleCreateEvent.Sku();
                sku.setSkuCode(item.getSkuCode());
                sku.setSkuName(item.getSkuName());
                return sku;
            }).collect(Collectors.toList()));
            SpringUtil.publishEvent(event);
        });
        Map<String, List<AfterSaleItem>> afterSaleItemsGroup = afterSaleItems.stream()
                .collect(Collectors.groupingBy(AfterSaleItem::getAfterSaleSn));
        List<AfterSaleApplyOutBO.Result> results = Lists.newArrayList();
        afterSaleItemsGroup.forEach((k, v) -> {
            AfterSaleApplyOutBO.Result result = new AfterSaleApplyOutBO.Result();
            result.setAfterSaleSn(k);
            result.setBizAfterSaleSn(CollUtil.getFirst(v).getBizAfterSaleSn());
            result.setOrderSn(CollUtil.getFirst(v).getOrderSn());
            result.setSkuCodes(v.stream().map(AfterSaleItem::getSkuCode).collect(Collectors.toList()));
            results.add(result);
        });
        return AfterSaleApplyOutBO.builder().results(results).build();
    }

    @Override
    public List<AfterSaleWayBillOutBO> queryAfterSaleWaybills(String afterSaleSn) {
        List<AfterSalesLogistic> afterSalesLogistics = afterSalesLogisticsRepository.list(Wrappers.<AfterSalesLogistic>lambdaQuery()
                .eq(AfterSalesLogistic::getAfterSaleSn, afterSaleSn));
        return afterSalesLogistics.stream().map(afterSaleServiceConverter::assembleAfterSaleWayBill)
                .collect(Collectors.toList());
    }

    @Override
    public AfterSalePickUpBO queryPickUp(String afterSaleSn) {
        AfterSalePickUp afterSalePickUp =
                afterSalesPickupRepository.getOne(Wrappers.<AfterSalePickUp>lambdaQuery().eq(AfterSalePickUp::getAfterSaleSn, afterSaleSn));
        return afterSaleServiceConverter.assembleAfterSalePickUp(afterSalePickUp);
    }

    @Override
    public AfterSaleReturnShipmentBO queryReturnShipment(String afterSalesSn) {
        AfterSaleReturn po = afterSalesReturnRepository.getOne(Wrappers.<AfterSaleReturn>lambdaQuery().eq(AfterSaleReturn::getAfterSaleSn, afterSalesSn));
        return afterSaleServiceConverter.assembleAfterSaleReturnShipment(po);
    }

    @Override
    public List<AfterSaleItemOutBO> queryAfterSaleItems(AfterSaleItemQuery query) {
        List<AfterSaleItem> list = afterSaleItemRepository.list(
                Wrappers.<AfterSaleItem>lambdaQuery()
                        .eq(StringUtils.isNotBlank(query.getAfterSaleSn()), AfterSaleItem::getBizAfterSaleSn, query.getAfterSaleSn())
                        .in(CollectionUtils.isNotEmpty(query.getOrderSns()), AfterSaleItem::getOrderSn, query.getOrderSns())
                        .in(CollectionUtils.isNotEmpty(query.getIncludeAfterSaleStatusList()), AfterSaleItem::getAfterSaleStatus, query.getIncludeAfterSaleStatusList())
                        .notIn(CollectionUtils.isNotEmpty(query.getExcludeAfterSaleStatusList()), AfterSaleItem::getAfterSaleStatus, query.getExcludeAfterSaleStatusList())
        );
        return list.stream().map(afterSaleServiceConverter::assembleAfterSaleItem).collect(Collectors.toList());
    }

    @Override
    public Page<AfterSaleListVO> queryPage(IPage<AfterSaleListVO> page, AfterSaleApplyQueryDTO afterSaleApplyQuery) {
        return afterSaleRepository.queryPage(page, afterSaleApplyQuery);
    }
}
